#include <math.h>
#include <glib/gi18n.h>
#include <gtk/gtk.h>
#include "demo.h"

static void print_attribute(PangoAttribute* attr)
{
  GEnumClass *class;
  GEnumValue *value;

  g_print("\t[%d,%d]", attr->start_index, attr->end_index);

  class = g_type_class_ref (pango_attr_type_get_type ());
  value = g_enum_get_value (class, attr->klass->type);
  g_print("%s=", value->value_nick);
  g_type_class_unref (class);

  switch (attr->klass->type)
    {
    case PANGO_ATTR_LANGUAGE:
      g_print("%s",pango_language_to_string (((PangoAttrLanguage *)attr)->value));
      break;
    case PANGO_ATTR_FAMILY:
    case PANGO_ATTR_FONT_FEATURES:
      g_print("%s", ((PangoAttrString *)attr)->value);
      break;
    case PANGO_ATTR_STYLE:
    case PANGO_ATTR_WEIGHT:
    case PANGO_ATTR_VARIANT:
    case PANGO_ATTR_STRETCH:
    case PANGO_ATTR_SIZE:
    case PANGO_ATTR_ABSOLUTE_SIZE:
    case PANGO_ATTR_UNDERLINE:
    // case PANGO_ATTR_OVERLINE:
    case PANGO_ATTR_STRIKETHROUGH:
    case PANGO_ATTR_RISE:
    case PANGO_ATTR_FALLBACK:
    case PANGO_ATTR_LETTER_SPACING:
    case PANGO_ATTR_GRAVITY:
    case PANGO_ATTR_GRAVITY_HINT:
    case PANGO_ATTR_FOREGROUND_ALPHA:
    case PANGO_ATTR_BACKGROUND_ALPHA:
    case PANGO_ATTR_ALLOW_BREAKS:
    case PANGO_ATTR_INSERT_HYPHENS:
    case PANGO_ATTR_SHOW:
      g_print("%d", ((PangoAttrInt *)attr)->value);
      break;
    case PANGO_ATTR_FONT_DESC:
      {
        char *text = pango_font_description_to_string (((PangoAttrFontDesc *)attr)->desc);
        g_print("%s", text);
        g_free (text);
      }
      break;
    case PANGO_ATTR_FOREGROUND:
    case PANGO_ATTR_BACKGROUND:
    case PANGO_ATTR_UNDERLINE_COLOR:
    // case PANGO_ATTR_OVERLINE_COLOR:
    case PANGO_ATTR_STRIKETHROUGH_COLOR:
      {
        char *text = pango_color_to_string (&((PangoAttrColor *)attr)->color);
        g_print("%s", text);
        g_free (text);
      }
      break;
    case PANGO_ATTR_SHAPE:
      g_print("shape");
      break;
    case PANGO_ATTR_SCALE:
      {
        char val[20];

        g_ascii_formatd (val, 20, "%f", ((PangoAttrFloat *)attr)->value);
        g_print("%s", val);
      }
      break;
    default:
      g_assert_not_reached ();
      break;
    }

}


static void print_layout_info(PangoLayout* layout)
{

    g_print("pango info:\n");

    //font description
    const PangoFontDescription *desc;
    desc = pango_layout_get_font_description(layout);
    if(desc)
    {
        gchar* str;    
        str = pango_font_description_to_string(desc);
        g_print("\tfontDescription: %s\n", str);
        g_free(str);
    }
    else
    {
        g_print("\tfontDescription: NULL\n");
    }


    //width and height
    int width;
    int height;
    width = pango_layout_get_width(layout);
    height = pango_layout_get_height(layout);
    g_print("\tlayout width,height: %d,%d\n", width, height);

    //attrList
    PangoAttrList *attrList = pango_layout_get_attributes(layout);
    if(attrList)
    {
      g_print("\t---------attrList\n");

      PangoAttrIterator *iter;
      iter = pango_attr_list_get_iterator(attrList);

      do
      {
          gint start, end;
          pango_attr_iterator_range(iter, &start, &end);
          g_print("\trange: %d ~ %d\n", start, end);

          GSList *list, *l;
          list = pango_attr_iterator_get_attrs(iter);
          for(l = list; l; l = l->next)
          {
              PangoAttribute *attr = list->data;
              print_attribute(attr);
              g_print("\n");

          }
          g_slist_free_full (list, (GDestroyNotify)pango_attribute_destroy);
      

      } while(pango_attr_iterator_next(iter));

      pango_attr_iterator_destroy(iter);

    }

}

static void print_lines(PangoLayout* layout)
{
    PangoLayoutIter *iter;
    PangoLayoutLine *line;
    const gchar* text;
    gchar* str;
    gint i = 0;

    g_print("\t--------- lines\n");
    iter = pango_layout_get_iter(layout);
    text = pango_layout_get_text(layout);

    do
    {
        i++;
        line = pango_layout_iter_get_line(iter);
        str = g_strndup(text + line->start_index, line->length);
        g_print("\ti=%d,index=%d,paragraph-start=%d, '%s'\n", i, line->start_index, line->is_paragraph_start, str);
        g_free(str);
        
    } while (pango_layout_iter_next_line(iter));
    


    pango_layout_iter_free (iter);
}


static void print_runs(PangoLayout* layout)
{
    PangoLayoutIter *iter;
    PangoLayoutRun *run;
    const gchar* text;
    gint i = 0;

    g_print("\t--------- runs\n");
    iter = pango_layout_get_iter(layout);
    text = pango_layout_get_text(layout);

    do
    {
        i++;
        run = pango_layout_iter_get_run(iter);
        if(run)
        {
            gchar* str;
            str = g_strndup(text + run->item->offset, run->item->length);
            g_print("\ti=%d,index=%d,level=%d,script=%d,lang=%s '%s'\n"
                    , i
                    , run->item->offset
                    , run->item->analysis.level
                    ,run->item->analysis.script
                    , pango_language_to_string(run->item->analysis.language)
                    , str);
            g_free(str);
        }        
    } while (pango_layout_iter_next_run(iter));   


    pango_layout_iter_free (iter);
}
//derived from pango-html-1.42.4/pango-Cairo-Rendering.html
static gboolean on_draw(GtkWidget *widget, cairo_t *cr, gpointer data)
{
    guint width, height;
    // GdkRGBA color;
    GtkStyleContext *context;


    context = gtk_widget_get_style_context (widget);
    width = gtk_widget_get_allocated_width (widget);
    height = gtk_widget_get_allocated_height (widget);
    g_print("on_draw()....width=%d,height=%d\n", width, height);

    g_print("default lang= %s\n"
                , pango_language_to_string(pango_language_get_default())
                );

    PangoLanguage *zh_lang = pango_language_from_string("zh");
    PangoScript script = g_unichar_get_script(0x4e2d);

    g_print("zh lang= %s, script=%d\n"
                , pango_language_to_string(zh_lang)
                , script
                );

    gtk_render_background (context, cr, 0, 0, width, height);
    draw_coord(cr, 0, 0);

    PangoLayout *layout;
    PangoFontDescription *desc;

    cairo_save (cr);
    // cairo_translate (cr, 10, 10);

    //#1.create layout

    layout = pango_cairo_create_layout (cr);
    print_layout_info(layout);

    desc = pango_font_description_from_string ("sans 36");
    pango_layout_set_font_description (layout, desc);
    pango_font_description_free (desc);


    pango_layout_set_width (layout, 800 * PANGO_SCALE);
    char* text="Hi 中国한국어, yeah! Nice.\nHello.";
    pango_layout_set_text (layout, text, -1);


    //draw text

    //cairo_move_to(cr, 10, 10);
    cairo_translate (cr, 10, 10);    
    cairo_set_source_rgb(cr, 1, 0, 0);

    pango_cairo_show_layout(cr, layout);

    //draw layout bounds

    PangoRectangle ink_rect;
    PangoRectangle logical_rect;

    pango_layout_get_pixel_extents(layout, &ink_rect, &logical_rect);
    cairo_rectangle(cr, logical_rect.x, logical_rect.y,logical_rect.width, logical_rect.height);
    cairo_set_line_width(cr, 1.0);
    cairo_set_source_rgba(cr, 0,1,0, 0.7);
    cairo_stroke(cr);    

    cairo_rectangle(cr, ink_rect.x, ink_rect.y,ink_rect.width, ink_rect.height);
    cairo_set_line_width(cr, 1.0);
    cairo_set_source_rgba(cr, 0,0,1, 0.7);
    cairo_stroke(cr);    

    g_print("logical x, width: %d, %d; ink x, width: %d, %d; logical width: %d, \n"
              , logical_rect.x, logical_rect.width
              , ink_rect.x, ink_rect.width
              , PANGO_PIXELS(pango_layout_get_width(layout))
              );


    //draw char bounds
    PangoLayoutIter *itr;
    itr = pango_layout_get_iter(layout);

    cairo_set_line_width(cr,1.0);
    cairo_set_source_rgba(cr, 0,0.5,0.5, 0.7);
    do
    {
      pango_layout_iter_get_char_extents(itr, &logical_rect);
      pango_extents_to_pixels(&logical_rect, NULL);
      cairo_rectangle(cr, logical_rect.x, logical_rect.y,logical_rect.width, logical_rect.height);
      cairo_stroke(cr);
    } while (pango_layout_iter_next_char(itr));
    

    pango_layout_iter_free(itr);


    //print layout info

    print_layout_info(layout);
    print_lines(layout);
    print_runs(layout);

    g_object_unref (layout);
    cairo_restore(cr);



    return FALSE;
}

void do_pango_layout(GtkBox *parent)
{
    GtkWidget* frame;
    GtkWidget* drawing_area;

    frame = gtk_frame_new("pangoLayout");
    gtk_container_set_border_width(GTK_CONTAINER(frame), 10);
    gtk_box_pack_start(parent, frame, TRUE, TRUE, 0);

    drawing_area = gtk_drawing_area_new();
    gtk_container_add(GTK_CONTAINER(frame), drawing_area);

    g_signal_connect(drawing_area, "draw", G_CALLBACK (on_draw), NULL);        

    gtk_widget_show_all(GTK_WIDGET(parent));    
}